home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / others / ole_101.zip / PATRON.ZIP / BLACKBOX.C next >
C/C++ Source or Header  |  1992-04-13  |  16KB  |  600 lines

  1. /*
  2.  * BLACKBOX.C
  3.  *
  4.  * Code for a BlackBox window that will contain and OLE object.
  5.  *
  6.  * Copyright(c) Microsoft Corp. 1992 All Rights Reserved
  7.  */
  8.  
  9.  
  10. #include <windows.h>
  11. #include <ole.h>
  12. #include "oclient.h"
  13. #include "patron.h"
  14. #include "blackbox.h"
  15.  
  16.  
  17.  
  18. /*
  19.  * FileObjectDefaults
  20.  *
  21.  * Purpose:
  22.  *  Fills a FILEOBJECT structure with defaults for a BlackBox window:
  23.  *  wID, rc, and szName.  dwSize is not affected.  This is so
  24.  *  HBlackBoxCreate can take a FILEOBJECT pointer for the initial
  25.  *  values of these fields.
  26.  *
  27.  * Parameters:
  28.  *  pFO             LPFILEOBJECT to fill.
  29.  *
  30.  * Return Value:
  31.  *  None
  32.  */
  33.  
  34. void FAR PASCAL FileObjectDefaults(LPFILEOBJECT pFO)
  35.     {
  36.     pFO->wID=WIDGetNext(FALSE);
  37.     PRectGetNext(&pFO->rc, FALSE);
  38.  
  39.     //Don't use a colon or backslash in the name.  Some apps may strip it.
  40.     wsprintf(pFO->szName, "%s[%d]", (LPSTR)rgpsz[IDS_CLASSBLACKBOX], pFO->wID);
  41.     return;
  42.     }
  43.  
  44.  
  45.  
  46.  
  47.  
  48. /*
  49.  * HBlackBoxCreate
  50.  *
  51.  * Purpose:
  52.  *  Constructor function for the black box window, simply calling
  53.  *  CreateWindow and activating that window.  Initial position, parentage,
  54.  *  and pointers to an LPCLIENT and an LPOBJECT are given by the caller.
  55.  *
  56.  * Parameters:
  57.  *  hWndParent      HWND of the parent window
  58.  *  pFO             LPFILEOBJECT containing ID, rectangle, and name.  If
  59.  *                  this is NULL this function calls FileObjectDefault to
  60.  *                  fill one.
  61.  *  fShow           BOOL TRUE to show and activate the window.  FALSE
  62.  *                  creates it hidden.
  63.  *  pObj            LPOBJECT to associate with this window.
  64.  *
  65.  * Return Value:
  66.  *  HWND            Handle to the new window if successful, FALSE otherwise.
  67.  */
  68.  
  69. HWND FAR PASCAL HBlackBoxCreate(HWND hWndParent, LPFILEOBJECT pFO,
  70.                                 BOOL fShow, LPOBJECT pObj)
  71.     {
  72.     OLESTATUS   os;
  73.     FILEOBJECT  fo;
  74.     HWND        hWnd=NULL;
  75.     HANDLE      hInst;
  76.     DWORD       dwStyle;
  77.  
  78.     if (NULL==hWndParent || NULL==pObj)
  79.         return NULL;
  80.  
  81.     if (NULL==pFO)
  82.         {
  83.         pFO=&fo;
  84.         FileObjectDefaults(pFO);
  85.         }
  86.  
  87.     hInst=GetWindowWord(hWndParent, GWW_HINSTANCE);
  88.  
  89.     //Set the visible bit if so requested.
  90.     dwStyle=WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME;
  91.     dwStyle |= (fShow) ? WS_VISIBLE : 0L;
  92.  
  93.     //Create the window initially hidden.
  94.     hWnd=CreateWindow(rgpsz[IDS_CLASSBLACKBOX], pFO->szName, dwStyle,
  95.                       pFO->rc.left, pFO->rc.top,
  96.                       pFO->rc.right-pFO->rc.left, pFO->rc.bottom-pFO->rc.top,
  97.                       hWndParent, pFO->wID, hInst, (LPVOID)pObj);
  98.  
  99.     //Activate this window.
  100.     if (NULL!=hWnd && fShow)
  101.         {
  102.         BringWindowToTop(hWnd);
  103.         SendMessage(hWnd, WM_NCACTIVATE, TRUE, 0L);
  104.         FDirtySet(TRUE);
  105.         }
  106.  
  107.     //Delete the object we were given if we fail.
  108.     if (NULL==hWnd)
  109.         {
  110.         //Cleanup the object we created.
  111.         os=OleDelete(pObj->pObj);
  112.  
  113.         OsError(os, pObj->pDoc, pObj, TRUE);
  114.  
  115.         //Cleanup what was given to us.
  116.         PObjectFree(pObj->pDoc, pObj);
  117.         }
  118.  
  119.     return hWnd;
  120.     }
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128. /*
  129.  * BlackBoxWndProc
  130.  *
  131.  * Purpose:
  132.  *  Window class procedure for the BlackBox window.  Standard callback.
  133.  *
  134.  * Parameters:
  135.  *  Standard.
  136.  *
  137.  * Return Value:
  138.  *  Standard.
  139.  */
  140.  
  141. long FAR PASCAL BlackBoxWndProc(HWND hWnd, UINT iMsg, UINT wParam, LONG lParam)
  142.     {
  143.     LPCREATESTRUCT  pCreate;
  144.     PBLACKBOX       pBL;
  145.     HANDLE          hMem;
  146.     HWND            hWndParent;
  147.     HDC             hDC;
  148.     PAINTSTRUCT     ps;
  149.     RECT            rc;
  150.     WORD            cx, cy;
  151.  
  152.  
  153.     hWndParent=GetParent(hWnd);
  154.     pBL=(PBLACKBOX)GetWindowWord(hWnd, GWW_BLACKBOXHMEM);
  155.  
  156.     if (WM_USER <= iMsg)
  157.         return LBlackBoxUserMessage(hWnd, iMsg, wParam, lParam, pBL);
  158.  
  159.  
  160.     switch (iMsg)
  161.         {
  162.         case WM_NCCREATE:
  163.             hMem=LocalAlloc(LPTR, CBBLACKBOX);
  164.  
  165.             if (NULL==hMem)
  166.                 return 0L;
  167.  
  168.             SetWindowWord(hWnd, GWW_BLACKBOXHMEM, (HANDLE)hMem);
  169.  
  170.             //Must use DefWindowProc to correctly set window text.
  171.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  172.  
  173.  
  174.         case WM_CREATE:
  175.             pCreate=(LPCREATESTRUCT)lParam;
  176.             pBL->pObj=(LPOBJECT)pCreate->lpCreateParams;
  177.  
  178.             //Initialize this window's OBJECT structure
  179.             if (NULL==PObjectInitialize(pBL->pObj, pBL->pObj->pDoc))
  180.                 {
  181.                 /*
  182.                  * Prevent WM_NCDESTROY from freeing structure.  Let
  183.                  * HBlackBoxCreate do it instead.
  184.                  */
  185.                 pBL->pObj=NULL;
  186.                 return -1L;
  187.                 }
  188.  
  189.             //Store our window handle in user-defined data space.
  190.             pBL->pObj->hData=hWnd;
  191.             pBL->fDrag=FALSE;
  192.             return 1L;
  193.  
  194.  
  195.         case WM_NCDESTROY:
  196.             if (NULL==pBL)
  197.                 break;
  198.  
  199.             if (NULL!=pBL->pObj);
  200.                 PObjectFree(pBL->pObj->pDoc, pBL->pObj);
  201.  
  202.             if (NULL!=pBL)
  203.                 LocalFree((HANDLE)pBL);
  204.             break;
  205.  
  206.  
  207.         case WM_NCACTIVATE:
  208.             if (1==wParam)
  209.                 {
  210.                 //Notify the parent that we've been activated.
  211.                 wParam=GetWindowWord(hWnd, GWW_ID);
  212.                 lParam=MAKELONG(hWnd, BBN_ACTIVATED);
  213.                 SendMessage(hWndParent, WM_COMMAND, wParam, lParam);
  214.                 }
  215.  
  216.             //Must do this to affect activation properly.
  217.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  218.  
  219.  
  220.         case WM_SIZE:
  221.             //Inform the object that we changed size.
  222.             if (pBL->fUserResize)
  223.                 {
  224.                 /*
  225.                  * Get the screen coordinates for the *client* area of
  226.                  * this rectangle for passing to OleSetBounds through
  227.                  * FObjectRectSet.
  228.                  */
  229.                 GetWindowRect(hWnd, &rc);
  230.  
  231.                 //Subtract the borders.
  232.                 cx=GetSystemMetrics(SM_CXFRAME);
  233.                 cy=GetSystemMetrics(SM_CYFRAME);
  234.                 InflateRect(&rc, -(int)cx, -(int)cy);
  235.  
  236.                 FObjectRectSet(pBL->pObj->pDoc, pBL->pObj, &rc, MM_TEXT);
  237.  
  238.                 pBL->fUserResize=FALSE;
  239.  
  240.                 wParam=GetWindowWord(hWnd, GWW_ID);
  241.                 lParam=MAKELONG(hWnd, BBN_SIZED);
  242.                 SendMessage(hWndParent, WM_COMMAND, wParam, lParam);
  243.                 }
  244.  
  245.             break;
  246.  
  247.  
  248.         case WM_PAINT:
  249.             hDC=BeginPaint(hWnd, &ps);
  250.  
  251.             //Draw the object and show it as opened if it happens to be.
  252.             GetClientRect(hWnd, &rc);
  253.             FObjectPaint(hDC, &rc, pBL->pObj);
  254.  
  255.             EndPaint(hWnd, &ps);
  256.             break;
  257.  
  258.  
  259.         case WM_NCLBUTTONDBLCLK:
  260.             //Go execute the primary verb.
  261.             SendMessage(hWnd, BBM_VERBEXECUTE, 0, 0L);
  262.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  263.  
  264.         case WM_NCHITTEST:
  265.             /*
  266.              * Make the whole client area act like a caption bar, but do
  267.              * not interfere with the sizing borders.
  268.              */
  269.             lParam=DefWindowProc(hWnd, iMsg, wParam, lParam);
  270.  
  271.             if ((LONG)HTCLIENT==lParam)
  272.                 lParam=(LONG)HTCAPTION;
  273.  
  274.             return lParam;
  275.  
  276.  
  277.         case WM_NCLBUTTONDOWN:
  278.             //Activate this window.  WM_NCACTIVATE takes care of deactivating.
  279.             BringWindowToTop(hWnd);
  280.             SendMessage(hWnd, WM_NCACTIVATE, 1, 0L);
  281.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  282.  
  283.  
  284.         case WM_SYSCOMMAND:
  285.             if (SC_SIZE==(wParam & 0xfff0))
  286.                 {
  287.                 //Indicate that next WM_SIZE was user-initiated.
  288.                 pBL->fUserResize=TRUE;
  289.                 }
  290.  
  291.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  292.  
  293.         default:
  294.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  295.         }
  296.  
  297.     return 0L;
  298.     }
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305. /*
  306.  * LBlackBoxUserMessage
  307.  *
  308.  * Purpose:
  309.  *  Handles all window-specific messages WM_USER and greater,
  310.  *  for the BlackBox window:
  311.  *
  312.  *
  313.  * Parameters:
  314.  *  hWnd            HWND of the BlackBox window.
  315.  *  iMsg            WORD message to process.
  316.  *  wParam          WORD parameter of the message.
  317.  *  lParam          LONG parameter of the message.
  318.  *  pBL             PBLACKBOX to the window's extra data structure.
  319.  *
  320.  * Return Value:
  321.  *  DWORD           Value to return from the window procedure
  322.  *                  that recieved the message.
  323.  */
  324.  
  325. DWORD PASCAL LBlackBoxUserMessage(HWND hWnd, WORD iMsg, WORD wParam,
  326.                                   LONG lParam, PBLACKBOX pBL)
  327.     {
  328.     DWORD           dwRet=0L;
  329.     HWND            hWndParent;
  330.     LPRECT          pRect;
  331.     RECT            rc;
  332.     OLESTATUS       os;
  333.  
  334.     if (NULL==pBL)
  335.         return 0L;
  336.  
  337.     hWndParent=GetParent(hWnd);
  338.  
  339.     switch (iMsg)
  340.         {
  341.         case BBM_RECTSET:
  342.             /*
  343.              * lParam points to a RECT structure containing the new
  344.              * coordinates for the window in terms of the parent's
  345.              * client area, as we store in the files for this application.
  346.              */
  347.             if ((LONG)NULL==lParam)
  348.                 break;
  349.  
  350.             pRect=(LPRECT)lParam;
  351.             AdjustWindowRect(pRect, WS_BORDER | WS_THICKFRAME, FALSE);
  352.  
  353.             SetWindowPos(hWnd, NULL, pRect->left, pRect->top,
  354.                          pRect->right-pRect->left,
  355.                          pRect->bottom-pRect->top, SWP_NOZORDER);
  356.  
  357.             InvalidateRect(hWnd, NULL, TRUE);
  358.             UpdateWindow(hWnd);
  359.             dwRet=1L;
  360.             break;
  361.  
  362.  
  363.         case BBM_RECTGET:
  364.             /*
  365.              * lParam points to an LPRECT to fill with the coordinates
  366.              * of the window in terms of the parent's client area.
  367.              */
  368.  
  369.             if ((LONG)NULL==lParam)
  370.                 break;
  371.  
  372.             PRectWindowGet(hWnd, (LPRECT)lParam, hWndParent);
  373.             dwRet=1L;
  374.             break;
  375.  
  376.  
  377.         case BBM_POBJECTGET:
  378.             return (DWORD)pBL->pObj;
  379.  
  380.         case BBM_OBJECTNOTIFY:
  381.             if (OLE_RENAMED==wParam)
  382.                 {
  383.                 PObjectInitialize(pBL->pObj, pBL->pObj->pDoc);
  384.                 break;
  385.                 }
  386.  
  387.             if (OLE_SAVED==wParam || OLE_CHANGED==wParam)
  388.                 {
  389.                 //Get the size of the object we created and scale the new window to fit.
  390.                 if (FObjectRectGet(pBL->pObj, &rc, MM_TEXT))
  391.                     {
  392.                     if (!pBL->fUserResize)
  393.                         {
  394.                         AdjustWindowRect(&rc, WS_BORDER | WS_THICKFRAME, FALSE);
  395.  
  396.                         SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left,
  397.                                      rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER);
  398.                         }
  399.  
  400.                     wParam=GetWindowWord(hWnd, GWW_ID);
  401.                     lParam=MAKELONG(hWnd, BBN_CHANGED);
  402.                     SendMessage(hWndParent, WM_COMMAND, wParam, lParam);
  403.                     }
  404.                 }
  405.  
  406.             InvalidateRect(hWnd, NULL, TRUE);
  407.             UpdateWindow(hWnd);
  408.             break;
  409.  
  410.  
  411.         case BBM_VERBEXECUTE:
  412.             /*
  413.              * The original OLE documentation states that OleSetHostNames
  414.              * should be called the first time the object is activated.
  415.              * OleSetHostNames simply sets names with OLECLI that it passes
  416.              * to a server's DocSetHostNames method when the object is
  417.              * opened.  You don't really *have* to call OleSetHostNames
  418.              * here as long as you call it once before opening the object.
  419.              *
  420.              * We specifically do it within PObjectAllocate, which only
  421.              * may be slightly inefficient if we never activate the object,
  422.              * but it eliminates tracking whether or not we've been activated
  423.              * yet.
  424.              */
  425.  
  426.             GetClientRect(hWnd, &rc);
  427.  
  428.             /*
  429.              * Check if the server is busy.  You want to check now because
  430.              * you could call FOLEReleaseWait and then continue in
  431.              * OleActivate.  Here we simply notify the user and exit.
  432.              */
  433.             os=OleQueryReleaseStatus(pBL->pObj->pObj);
  434.             os=OsError(os, pBL->pObj->pDoc, pBL->pObj, TRUE);
  435.  
  436.             if (OLE_OK!=os)
  437.                 break;
  438.  
  439.             //wParam holds the verb, starting at 0.
  440.             os=OleActivate(pBL->pObj->pObj, wParam, TRUE, TRUE, hWndParent, &rc);
  441.  
  442.             if (OLE_OK==OsError(os, pBL->pObj->pDoc, pBL->pObj, TRUE))
  443.                 {
  444.                 //Force a repaint to insure that the window shows the open state.
  445.                 pBL->pObj->fOpen=TRUE;
  446.                 InvalidateRect(hWnd, NULL, TRUE);
  447.                 UpdateWindow(hWnd);
  448.                 }
  449.  
  450.             break;
  451.  
  452.         default:
  453.             break;
  454.         }
  455.  
  456.     return dwRet;
  457.     }
  458.  
  459.  
  460.  
  461.  
  462. /*
  463.  * PRectWindowGet
  464.  *
  465.  * Purpose:
  466.  *  Fills a rectangle with the coordinates of the given child window
  467.  *  in terms of the CLIENT area of the parent window.
  468.  *
  469.  * Parameters:
  470.  *  hWnd            HWND of the window to get the rectangle for.
  471.  *  pRect           LPRECT to where to store the dimensions.
  472.  *  hWndParent      HWND of the parent window whose client area concerns us.
  473.  *
  474.  * Return Value:
  475.  *  LPRECT          Same as pRect passed.
  476.  */
  477.  
  478. LPRECT FAR PASCAL PRectWindowGet(HWND hWnd, LPRECT pRect, HWND hWndParent)
  479.     {
  480.     POINT       pt;
  481.  
  482.     if ((LPRECT)NULL==pRect)
  483.         return pRect;
  484.  
  485.     GetWindowRect(hWnd, pRect);
  486.  
  487.     /*
  488.      * Note, I use the POINT variable to make it clear what is going on
  489.      * instead of trying to be utterly efficient in a rarely used function.
  490.      */
  491.  
  492.     pt.x=pRect->left;
  493.     pt.y=pRect->top;
  494.     ScreenToClient(hWndParent, &pt);
  495.     pRect->left=pt.x;
  496.     pRect->top=pt.y;
  497.  
  498.     pt.x=pRect->right;
  499.     pt.y=pRect->bottom;
  500.     ScreenToClient(hWndParent, &pt);
  501.     pRect->right=pt.x;
  502.     pRect->bottom=pt.y;
  503.  
  504.     return pRect;
  505.     }
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513. /*
  514.  * WIDGetNext
  515.  *
  516.  * Purpose:
  517.  *  Returns the next ID value to use in creating a BLACKBOX window.
  518.  *  This function simply maintains a static counter.
  519.  *
  520.  * Parameters:
  521.  *  fReset          BOOL TRUE forces WIDGetNext to reset the ID to 1000,
  522.  *                  And 1000 is returned.
  523.  *
  524.  * Return Value:
  525.  *  WORD            Next ID value.
  526.  */
  527.  
  528. WORD FAR PASCAL WIDGetNext(BOOL fReset)
  529.     {
  530.     static WORD     wID=999;
  531.  
  532.     if (fReset)
  533.         {
  534.         wID=1000;
  535.         return wID;
  536.         }
  537.  
  538.     return ++wID;
  539.     }
  540.  
  541.  
  542.  
  543.  
  544. /*
  545.  * PRectGetNext
  546.  *
  547.  * Purpose:
  548.  *  Fills a RECT structure with the location and suggested size for
  549.  *  a new BlackBox window.  Prior to OLE, all windows are of the same
  550.  *  size, but once we paste OLE objects, we must use the size in which
  551.  *  they come.
  552.  *
  553.  * Parameters:
  554.  *  pRect           LPRECT in which to store the new coordinates.
  555.  *  fReset          BOOL TRUE to reset the coordinates to defaults.
  556.  *                  pRect is filled with these new defaults.
  557.  *
  558.  * Return Value:
  559.  *  LPRECT          Same as pRect passed in.  NULL if pRect is NULL.
  560.  */
  561.  
  562. LPRECT FAR PASCAL PRectGetNext(LPRECT pRect, BOOL fReset)
  563.     {
  564.     static WORD     x=0, y=0;
  565.     static WORD     cx=150, cy=150;
  566.  
  567.     if (fReset)
  568.         {
  569.         x=0;
  570.         y=0;
  571.         cx=150;
  572.         cy=150;
  573.  
  574.         if ((LPRECT)NULL!=pRect)
  575.             SetRect(pRect, x, y, x+cx, x+cy);
  576.  
  577.         return pRect;
  578.         }
  579.  
  580.     if ((LPRECT)NULL==pRect)
  581.         return (LPRECT)NULL;
  582.  
  583.     SetRect(pRect, x, y, x+cx, y+cy);
  584.  
  585.     x+=10;
  586.  
  587.     if (x > 200)
  588.         x=0;
  589.  
  590.     y+=10;
  591.  
  592.     if (y > 150)
  593.         y=0;
  594.  
  595.     cx=150;
  596.     cy=150;
  597.  
  598.     return pRect;
  599.     }
  600.